package com.qf.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.filter.FormLoginFilter;
import com.qf.filter.VerifyJWTFilter;
import com.qf.pojo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;


/**
 * @Description:
 * @Author: 杨林涛
 * @Date: 2022/8/29 0029 17:40
 */
@Configuration
public class SeruityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Autowired
    private UserDetailsService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        //设置跨域访问
        http.cors().configurationSource(getConfigSource());


        http.addFilter(new FormLoginFilter(authenticationManager()))
                .addFilter(new VerifyJWTFilter(authenticationManager()));

        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
            //当访问的资源需要登录，而现在又没有登录时，会执行这个端点对象的commence方法
            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException, IOException {
                //在这个方法中，需要向前端项目中响应一个未登录的信息
                Result result = Result.noLogin("请先登录");
                ObjectMapper om = new ObjectMapper();
                String json = om.writeValueAsString(result);
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write(json);
//                response.sendRedirect("http://localhost:82/pages/health-login.html");
//                request.getRequestDispatcher("/health-login.html").forward(request,response);
//                request.getRequestDispatcher("/health-login.html").forward(request,response);
            }
        }).accessDeniedHandler(new AccessDeniedHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                //在这个方法中，需要向前端项目中响应一个没有权限的信息
                Result result = Result.noAuth("无权访问");
                ObjectMapper om = new ObjectMapper();
                String json = om.writeValueAsString(result);

                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write(json);
            }
        });
        //设置哪些资源需要登录，哪些资源需要权限
        http.authorizeRequests()
                .antMatchers("**/**").authenticated()
                .antMatchers("/**/**").authenticated()
                .antMatchers("/**").permitAll();


        //禁止session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //设置无权限页面
    }
    //配置资源请求规则
    private CorsConfigurationSource getConfigSource() {
        //基于路径的同源匹配方式
        UrlBasedCorsConfigurationSource urlSource = new UrlBasedCorsConfigurationSource();

        CorsConfiguration config = new CorsConfiguration();
        // 表示允许任何服务器来访问我的资源
        config.setAllowedOrigins(Arrays.asList("http://localhost"));
        // 允许所有请求方式的跨域访问 默认只支持get请求
        config.setAllowedMethods(Arrays.asList("*"));
        // 允许所有头信息的携带
        config.setAllowedHeaders(Arrays.asList("*"));
        // 设置为ture，表示允许携带cookie认证信息（这个值一旦设置为true，origin的设置不允许在使用*了）
        config.setAllowCredentials(true);
        //  /** 表示所有这种路径的访问，都匹配这个同源设置
        urlSource.registerCorsConfiguration("/**",config);
        return urlSource;
    }
}
